package readcheck.aspect;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.lang3.tuple.Pair;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.CollectionUtils;
import readcheck.annotation.VerifyAnno;
import readcheck.config.CommonVerifySetting;
import utils.CommonUtils;
import utils.CompareUtils;
import utils.ThreadPoolExecutor;
import utils.VerifyThreadLocalUtils;

/**
 * @Author : orangeCy.奕
 * @Product : 猎豹养成产品源码
 * @Time : 2023/9/2
 * @Desc :
 */
@Aspect
public class VerifyAspect {

    @Resource
    private CommonVerifySetting commonVerifySetting;

    public void setCommonVerifySetting(CommonVerifySetting commonVerifySetting) {
        this.commonVerifySetting = commonVerifySetting;
    }

    @Pointcut("@annotation(com.orangecy.readverify.annotation.VerifyAnno)")
    public void verifyAnno() {}

    @Around("@annotation(verifyAnno)")
    public Object invoke(ProceedingJoinPoint pjp, VerifyAnno verifyAnno) {
        try {
            //从切换配置池中检查判断
            boolean  hitPreVerify = commonVerifySetting.hitPreVerify(verifyAnno.verifyMethod());
            if(!hitPreVerify) {
                return pjp.proceed();
            }
            //设置ThreadLocal变量，执行目标方法前
            VerifyThreadLocalUtils.set(false);

            //执行目标方法
            Object targetResult = pjp.proceed();

            ThreadPoolExecutor.MIGRATE_POOL.execute(() -> {
                VerifyThreadLocalUtils.set(true);
                try {
                    Object asyncResult = pjp.proceed();
                    String verifyField = commonVerifySetting.getVerifyField(verifyAnno.verifyMethod());
                    boolean compareRes = compare(targetResult,asyncResult,verifyField);
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            });
            return true;
        }catch (Throwable e) {

        }finally {
            VerifyThreadLocalUtils.remove();
        }
        return false;
    }

    private boolean compare(Object targetResult, Object asyncResult, String verifyField) {
        List<String> verifyFieldList = CommonUtils.strTransStringList(verifyField, CommonUtils.SEPARATE1);
        //对比返回集中类型
        if(targetResult instanceof List && asyncResult instanceof List) {
            List targetList = JSON.parseObject(JSON.toJSONString(targetResult), List.class);
            List asyncList = JSON.parseObject(JSON.toJSONString(asyncResult), List.class);
            if(CollectionUtils.isEmpty(targetList) && CollectionUtils.isEmpty(asyncList)) {
                return true;
            }
            if(CollectionUtils.isEmpty(targetList) || CollectionUtils.isEmpty(asyncList)) {
                return false;
            }
            if(((List<?>) targetResult).size() != asyncList.size()) {
                return false;
            }
            List<Boolean> tempVerify = Lists.newArrayList();

            for(int i = 0 ; i< ((List<?>) targetResult).size() ; i ++) {
                Pair<Boolean, String> compare = CompareUtils.compare(((List<?>) targetResult).get(i), asyncList.get(i), verifyFieldList);
                tempVerify.add(compare.getKey());
                if(compare.getValue().contains("old") || compare.getValue().contains("new")) {
                    //do collection diff log
                }
            }
            return tempVerify.stream().allMatch(Boolean.TRUE::equals);
        }
        Pair<Boolean, String> compare = CompareUtils.compare(targetResult, asyncResult, verifyFieldList);
        if(compare.getValue().contains("old") || compare.getValue().contains("new")) {
            //do single diff log
        }
        return compare.getKey();
    }
}
